
#ifndef TOOLS_CLIENT
#define TOOLS_CLIENT

#include <cstdint>
#include <cstring>
#include <functional>
#include <memory>
#include <string>
#ifndef INCLUDE_LOOP
#include "./../loop.h"
#endif

#ifndef INCLUDE_CHANNEL
#include "./../channel.h"
#endif

#ifndef TOOLS_DEFINE
#include "define.h"
#endif

#ifndef TOOLS_UTIL
#include "tools_util.h"
#endif

struct ClientConfig
{
    bool socket_block{false};
};

class Client : public std::enable_shared_from_this<Client>
{
public:
    Client(Loop * loop);
    ~Client();
    bool Connect(const std::string & url, ClientConfig config);
    bool Connect(const std::string & ip, uint16_t port, ClientConfig config);
    void MessageCallbackFunc(ClientMessage && func);
    void ErrorCallbackFunc(ClientError && func);
    void ConnectCallbackFunc(ClientConnect && func);
    void Close();
    int SendData(const uint8_t * data, int length);
private:
    bool Connection(UrlInfo & info, ClientConfig & config);
    void Message(std::shared_ptr<Channel> channel, std::shared_ptr<TcpSocket> socket);
    void Error(std::shared_ptr<Channel> channel, std::shared_ptr<TcpSocket> socket);
private:
    Loop * m_loop;
    ClientMessage m_message;
    ClientError   m_error;
    ClientConnect m_connect;
private:
    std::shared_ptr<TcpSocket>    m_socket;
    std::shared_ptr<SocketBuffer> m_socket_buffer;
    std::shared_ptr<Channel>      m_channel;
};

#endif
